﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using CapturarObjetos.Nucleo;

namespace CapturarObjetos.Objetos
{
    class Jogador : ObjetoJogo
    {
        public float DirecaoFrontal { get; set; }
        public int AlcanceMaximo { get; set; }

        public const float Velocidade = .75f;
        public const float VelocidadeDeCurva = 0.01f;
        private Model modelo_tiro;
        public String tipoTiro = "cubo";

        private List<Tiro> tiros;

        public static int ammo = 2;

        ClockTimer clock;

        public static List<Jogador> listaJogadores = new List<Jogador>();



        public Jogador(ContentManager Content, string _modelo, ClockTimer L)
            : base()
        {
            modelo_tiro = Content.Load<Model>(tipoTiro); ;
            Modelo = Content.Load<Model>(_modelo);
            DirecaoFrontal = 0.0f;
            AlcanceMaximo = 100;
            clock = L;

            tiros = new List<Tiro>();

            Jogador.listaJogadores.Add(this);
        }

        public void Update(GameTime gameTime, KeyboardState teclado_atual, KeyboardState teclado_anterior, MouseState mouse_atual, MouseState mouse_anterior, ContentManager Content)
        {
            //preciso testar *primeiro* se a posição futura é válida para não travar, por isso a guardo...
            Vector3 posicaoFutura = Posicao;

            //estas duas variáveis temporárias servem para o giro e o movimento
            float quantoVirar = 0, anguloTerreno = 0;
            Vector3 movimento = Vector3.Zero;

            #region movimentosPeloTeclado

            if (teclado_atual.IsKeyDown(Keys.A) || teclado_atual.IsKeyDown(Keys.Left))
            {
                quantoVirar = 1;
                 }
            else if (teclado_atual.IsKeyDown(Keys.D) || teclado_atual.IsKeyDown(Keys.Right))
            {
                quantoVirar = -1;
            }
            if (teclado_atual.IsKeyDown(Keys.Up) || teclado_atual.IsKeyDown(Keys.W))
            {
                //positivo, correto?
                //movimento.Z = -1;
                anguloTerreno = 1;
            }
            else if (teclado_atual.IsKeyDown(Keys.S) || teclado_atual.IsKeyDown(Keys.Down))
            {
                //movimento.Z = 1;
                anguloTerreno = -1;
            }
            if (teclado_atual.IsKeyDown(Keys.Z))
            {
                tipoTiro = "piramide";
            }
            if (teclado_atual.IsKeyDown(Keys.X))
            {
                tipoTiro = "cubo";
            }
            if (teclado_atual.IsKeyDown(Keys.C))
            {
                tipoTiro = "energia";
            }
            if (teclado_atual.IsKeyDown(Keys.V))
            {
                tipoTiro = "cilindro";              
            }

            #endregion

            #region movimentosPeloMouse
            // Verificação (1==1) introduzida para não precisar clicar com o mouse para executar a verificaçao do botão, a nível de testes de "OnMouseOver"
            if (mouse_atual.LeftButton == ButtonState.Pressed || 1==1)
            {
                if (new Rectangle(370, 300, 60, 60).Contains(mouse_atual.X, mouse_atual.Y))
                {
                    //movimento.Z = -1;
                    anguloTerreno = -1;
                }


                if (new Rectangle(370, 400, 60, 60).Contains(mouse_atual.X, mouse_atual.Y))
                {
                    //movimento.Z = 1;
                    anguloTerreno = 1;
                }

                if (new Rectangle(450, 350, 60, 60).Contains(mouse_atual.X, mouse_atual.Y))
                {
                    quantoVirar = -1;
                }

                if (new Rectangle(290, 350, 60, 60).Contains(mouse_atual.X, mouse_atual.Y))
                {
                    quantoVirar = 1;
                }
            }

            #endregion

            //o pra onde ele vai virar é corrigido pela velocidade de giro
            DirecaoFrontal += quantoVirar * VelocidadeDeCurva;
            //isto está aqui apenas pq esta variável tem outro nome na hora de desenhar...
            RotacaoY = DirecaoFrontal;

            // Alterar variavel de rotação X corrigido pela velocidade
            if (RotacaoX <= MathHelper.ToRadians(0))
                RotacaoX += anguloTerreno * VelocidadeDeCurva / 2;
            else
                RotacaoX = MathHelper.ToRadians(0);
            if (RotacaoX > MathHelper.ToRadians(-70))
                RotacaoX += anguloTerreno * VelocidadeDeCurva / 2;
            else
                RotacaoX = MathHelper.ToRadians(-70);


            //preciso girar meu objeto naquela direção antes de andar
            Matrix matrixOrientacao = Matrix.CreateRotationY(DirecaoFrontal);
            //ando com ele aquela quantidade de movimento naquela direcao de orientacao
            Vector3 velocidade = Vector3.Transform(movimento, matrixOrientacao);
            //corrijo pela escala da velocidade
            velocidade *= Velocidade;
            //agora sim esta será a nova posicao do objeto
            posicaoFutura = Posicao + velocidade;

            if (posicaoFutura.X > AlcanceMaximo)
            {
                posicaoFutura.X = AlcanceMaximo;
            }

            if (posicaoFutura.Z > AlcanceMaximo)
            {
                posicaoFutura.Z = AlcanceMaximo;
            }

            if (posicaoFutura.X < -AlcanceMaximo)
            {
                posicaoFutura.X = -AlcanceMaximo;
            }

            if (posicaoFutura.Z < -AlcanceMaximo)
            {
                posicaoFutura.Z = -AlcanceMaximo;
            }
            
            Posicao = posicaoFutura;


            // Atirando pelo teclado
            if (teclado_atual.IsKeyDown(Keys.Space) && !teclado_anterior.IsKeyDown(Keys.Space) && tiros.Count < ammo)
            {
                modelo_tiro = Content.Load<Model>(tipoTiro);
                Tiro tiro = new Tiro(modelo_tiro, Posicao, Matrix.CreateRotationX(RotacaoX) * Matrix.CreateRotationY(DirecaoFrontal), clock, tipoTiro);
                tiros.Add(tiro);
            }

            // Atirando pelo mouse
            if (new Rectangle(600, 350, 120, 60).Contains(mouse_atual.X, mouse_atual.Y) && tiros.Count < ammo - 1)
            {
                modelo_tiro = Content.Load<Model>(tipoTiro);
                Tiro tiro = new Tiro(modelo_tiro, Posicao, Matrix.CreateRotationX(RotacaoX) * Matrix.CreateRotationY(DirecaoFrontal), clock, tipoTiro);
                tiros.Add(tiro);
            }

            //só pra atualizar e marcar com nao ativo...
            foreach (Tiro tiro in tiros)
            {
                tiro.Update(gameTime, teclado_atual, teclado_anterior, mouse_atual, mouse_anterior);
                
            }

            //repercorrer para remover
            for(int i = 0; i< tiros.Count; i++)
            {
                if (tiros[i].Ativo == false)
                    tiros.RemoveAt(i);
            }
        }

        private bool ManterNoTabuleiro(Vector3 posicaoFutura)
        {
            if ((Math.Abs(posicaoFutura.X) > AlcanceMaximo) ||
                (Math.Abs(posicaoFutura.Z) > AlcanceMaximo))
                return false;
            return true;
        }
    }
}
